#include "sqlconnpool.h"

const int DEFAULT_CONN_SIZE = 10;

SqlConnPool::SqlConnPool()
    : curConnSize_(0)
    , freeConnSize_(0)
{

}

// 实现单例
SqlConnPool* SqlConnPool::instance()
{
    static SqlConnPool connPool;
    return &connPool;
}

// 初始化
void SqlConnPool::init(const char* host, int port,
                const char* user, const char* pwd,
                const char* dbName, int connSize = DEFAULT_CONN_SIZE)
{
    assert(connSize > 0);
    for(int i = 0; i < connSize; ++i) {
        MYSQL* sql = nullptr;
        // 初始化 MySQL 连接对象
        sql = mysql_init(sql);
        if(sql == nullptr) {
            LOG_ERROR("MYSQL init error!");
            assert(sql);
        }

        // 连接到数据库
        sql = mysql_real_connect(sql, host, user, pwd,
                                dbName, port, nullptr, 0);
        if(sql == nullptr) {
            LOG_ERROR("MYSQL Connect error!");
        } 
        connQue_.push(sql);
    }

    maxConnSize_ = connSize;
    sem_init(&sem_, 0, maxConnSize_);
}

// 获取连接
MYSQL* SqlConnPool::getConn()
{
    MYSQL* sql = nullptr;
    if(connQue_.empty()) {
        LOG_WARN("SqlConnPool busy!");
        return nullptr;
    } 

    sem_wait(&sem_);
    {
        std::lock_guard<std::mutex> lock(mtx_);
        sql = connQue_.front();
        connQue_.pop();
    }
    return sql;
}

// 释放连接
void SqlConnPool::freeConn(MYSQL* sql)
{
    assert(sql);
    std::lock_guard<std::mutex> lock(mtx_);
    connQue_.push(sql);
    sem_post(&sem_);
}

// 关闭连接池
void SqlConnPool::closePool()
{
    std::lock_guard<std::mutex> lock(mtx_);
    while(!connQue_.empty()) {
        auto item = connQue_.front();
        connQue_.pop();
        mysql_close(item);
    }
    // 清理 MySQL 库的资源
    mysql_library_end();
}

// 获取空闲连接的数量
int SqlConnPool::getFreeConnCount() 
{
    std::lock_guard<std::mutex> lock(mtx_);
    return connQue_.size();
}

SqlConnPool::~SqlConnPool()
{
    closePool();
}


